package com.lenovo.hawk.config;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.annotation.MapperScans;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DelegatingDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.*;

/**
 * 数据源配置信息
 *
 * @author Hsg
 */
@Configuration
//@MapperScan({"com.lenovo.hawk.dao.master", "com.lenovo.hawk.dao.slave"})
//@MapperScan("com.lenovo.hawk.dao.*")
@MapperScan(basePackages = "com.lenovo.hawk.dao.master", sqlSessionFactoryRef = "sqlSessionFactoryMaster")
@MapperScan(basePackages = "com.lenovo.hawk.dao.slave", sqlSessionFactoryRef = "sqlSessionFactorySlave")
//@MapperScans({@MapperScan(basePackages = "com.lenovo.hawk.dao.master", sqlSessionFactoryRef = "sqlSessionFactoryMaster"),
//        @MapperScan(basePackages = "com.lenovo.hawk.dao.slave", sqlSessionFactoryRef = "sqlSessionFactorySlave")})
@Slf4j
@Data
public class DruidConfig {
    @Autowired
    private ApplicationContext applicationContext;

    //    private Map<String, AbstractRoutingDataSource> dynamicDataSourceMap = new HashMap<>();
    private Map<String, DelegatingDataSource> dynamicDataSourceMap = new HashMap<>();
    private Map<String, SqlSessionFactoryBean> sqlSessionFactoryBeanMap = new HashMap<>();

    /**
     * Default DataSource
     *
     * @return
     */
    @Bean(name = "druidMySQLDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.druid.mysql")
    @ConditionalOnProperty(name = "master.type", havingValue = "mysql", matchIfMissing = true)
    public DataSource druidMySQLDataSource() {
        return new DruidDataSource();
    }

    @Bean(name = "druidOracleDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.druid.oracle")
    @ConditionalOnProperty(name = "slave.type", havingValue = "oracle", matchIfMissing = true)
    public DataSource druidOracleDataSource() {
        return new DruidDataSource();
    }

    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //配置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(druidMySQLDataSource());
        //配置多数据源
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("masterDataSource", druidMySQLDataSource());
        dataSourceMap.put("slaveDataSource", druidOracleDataSource());
        dynamicDataSource.setDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    @Bean
    @Primary
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource作为数据源则不能实现切换
        sessionFactory.setDataSource(dynamicDataSource());
//        sessionFactory.setTypeAliasesPackage("com.lenovo.hawk.pojo");    // 扫描Model
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setMapperLocations(resolver.getResources("classpath*:mapper/*.xml"));    // 扫描映射文件
//        sessionFactory.setMapperLocations(resolveMapperLocations());    // 扫描映射文件
        sqlSessionFactoryByMore();
        return sessionFactory;
    }

    public void sqlSessionFactoryByMore() throws Exception {
        MapperScan[] mapperScans = DruidConfig.class.getAnnotationsByType(MapperScan.class);
        for (MapperScan mapperScan : mapperScans) {
            String sqlSessionFactoryName = mapperScan.sqlSessionFactoryRef();
//        String[] sqlSessionFactoryNames = new String[]{"sqlSessionFactoryMaster", "sqlSessionFactorySlave"};
//        for (String sqlSessionFactoryName : sqlSessionFactoryNames) {
            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
            // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource作为数据源则不能实现切换
//            sessionFactory.setDataSource(dynamicDataSource());
//            if ("sqlSessionFactoryMaster".equals(sqlSessionFactoryName)) {
//            sessionFactory.setDataSource(druidMySQLDataSource());
//            } else {
//                sessionFactory.setDataSource(druidOracleDataSource());
//            }
//            AbstractRoutingDataSource dynamicDataSource = new AbstractRoutingDataSource() {
//                @Override
//                protected Object determineCurrentLookupKey() {
//                    return null;
//                }
//            };
            //配置默认数据源
//            dynamicDataSource.setDefaultTargetDataSource(druidMySQLDataSource());
            //配置多数据源
//            dynamicDataSource.setTargetDataSources(new HashMap<>());
//            dynamicDataSource.afterPropertiesSet();
            DelegatingDataSource dynamicDataSource = new DelegatingDataSource(druidMySQLDataSource());
            dynamicDataSourceMap.put(sqlSessionFactoryName, dynamicDataSource);
            sessionFactory.setDataSource(dynamicDataSource);
            sessionFactory.setMapperLocations(resolveMapperLocations());    // 扫描映射文件
            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
            defaultListableBeanFactory.registerSingleton(sqlSessionFactoryName, sessionFactory);
            sqlSessionFactoryBeanMap.put(sqlSessionFactoryName, sessionFactory);
        }
    }

    public Resource[] resolveMapperLocations() {
        ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
        List<String> mapperLocations = new ArrayList<>();
        mapperLocations.add("classpath*:mapper/*.xml");
        mapperLocations.add("classpath*:mybatis/**/*.xml");
        List<Resource> resources = new ArrayList();
        if (mapperLocations != null) {
            for (String mapperLocation : mapperLocations) {
                try {
                    Resource[] mappers = resourceResolver.getResources(mapperLocation);
                    resources.addAll(Arrays.asList(mappers));
                } catch (IOException e) {
                    // ignore
                }
            }
        }
        return resources.toArray(new Resource[resources.size()]);
    }

    /**
     * 事务配置  使用事务时在方法头部添加@Transactional注解即可
     *
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }

}
